/*
 * pileIdentifiants.c
 *
 *  Created on: 28 nov. 2011
 *      Author: arthur
 */

#include "pileIdentifiants.h"

pileIdentifiants * creerPileId() {
	pileIdentifiants * nouvellePile = (pileIdentifiants *) calloc(1,
			sizeof(pileIdentifiants));

	if (nouvellePile != 0) {
		nouvellePile->fctLvls = calloc(5, sizeof(int));
		nouvellePile->varLvls = calloc(5, sizeof(int));
		nouvellePile->fctPtrs = calloc(5, sizeof(void *));
		nouvellePile->varPtrs = calloc(5, sizeof(void *));
		nouvellePile->maxFct = 5;
		nouvellePile->maxVar = 5;
		nouvellePile->crtFct = -1;
		nouvellePile->crtVar = -1;

		if (nouvellePile->fctLvls == 0 || nouvellePile->varLvls == 0
				|| nouvellePile->fctPtrs == 0 || nouvellePile->varPtrs == 0) {
			libererPileId(nouvellePile);
			nouvellePile = 0;
		}
	}

	return nouvellePile;
}

void libererPileId(pileIdentifiants * pI) {
	if (pI != 0) {
		if (pI->fctLvls != 0) {
			free(pI->fctLvls);
		}
		if (pI->varLvls != 0) {
			free(pI->varLvls);
		}
		if (pI->fctPtrs != 0) {
			free(pI->fctPtrs);
		}
		if (pI->varPtrs != 0) {
			free(pI->varPtrs);
		}
		free(pI);
	}
}

void ajoutVariable(pileIdentifiants * pI, variable * varPtr, int varLvl) {
	if (pI->crtVar >= pI->maxVar) {
		variable ** tmpPtrs = calloc((pI->maxVar + 5), sizeof(variable *));
		void *oldPtrs = pI->varPtrs;
		pI->varPtrs = tmpPtrs;
		memcpy(pI->varPtrs, oldPtrs, pI->maxVar * sizeof(void *));

		int * tmpLvls = calloc((pI->maxVar + 5), sizeof(int *));
		int *oldLvls = pI->varLvls;
		pI->varLvls = tmpLvls;
		memcpy(pI->varLvls, oldLvls, pI->maxVar * sizeof(int *));

		if (pI->varPtrs != 0 && pI->varLvls != 0) {
			pI->maxVar += 5;
		}
	}
	if (pI->varPtrs != 0 && pI->varLvls != 0) {
		pI->crtVar++;
		pI->varPtrs[pI->crtVar] = varPtr;
		pI->varLvls[pI->crtVar] = varLvl;
	}
}

void ajoutFonction(pileIdentifiants * pI, fonction * fctPtr, int fctLvl) {
	if (pI->crtFct >= pI->maxFct) {
		fonction ** tmpPtrs = calloc((pI->maxFct + 5), sizeof(fonction *));
		void *oldPtrs = pI->fctPtrs;
		pI->fctPtrs = tmpPtrs;
		memcpy(pI->fctPtrs, oldPtrs, pI->maxFct * sizeof(void *));

		int * tmpLvls = calloc((pI->maxFct + 5), sizeof(int *));
		int *oldLvls = pI->fctLvls;
		pI->fctLvls = tmpLvls;
		memcpy(pI->fctLvls, oldLvls, pI->maxFct * sizeof(int *));

		if (pI->fctPtrs != 0 && pI->fctLvls != 0) {
			pI->maxFct += 5;
		}
	}
	if (pI->fctPtrs != 0 && pI->fctLvls != 0) {
		pI->crtFct++;
		pI->fctPtrs[pI->crtFct] = fctPtr;
		pI->fctLvls[pI->crtFct] = fctLvl;
	}
}

variable * retrouverVariable(pileIdentifiants * pI) {
	return pI->varPtrs[pI->crtVar];
}
fonction * retrouverFonction(pileIdentifiants * pI) {
	return pI->fctPtrs[pI->crtFct];
}

void supprimerNiveau(pileIdentifiants * pI, int lvl) {
	for (; pI->fctLvls[pI->crtFct] >= lvl && pI->crtFct >= 0; pI->crtFct--) {
		pI->fctPtrs[pI->crtFct] = 0;
		pI->fctLvls[pI->crtFct] = 0;
	}
	for (; pI->varLvls[pI->crtVar] >= lvl && pI->crtVar >= 0; pI->crtVar--) {
		pI->varPtrs[pI->crtVar] = 0;
		pI->varLvls[pI->crtVar] = 0;
	}

}

int variableExisteAuNiveau(pileIdentifiants * pI, int lvl) {
	if (pI->varLvls[pI->crtVar] >= lvl) {
		return 1;
	}
	return 0;
}
int fonctionExisteAuNiveau(pileIdentifiants * pI, int lvl) {
	if (pI->fctLvls[pI->crtFct] >= lvl) {
		return 1;
	}
	return 0;
}

void afficherPile(pileIdentifiants * pI) {
	int i;
	for (i = 0; i <= pI->crtVar; i++) {
		printf("\tVariable niveau %d: ", pI->varLvls[i]);
		afficherVariable(pI->varPtrs[i]);
	}
	for (i = 0; i <= pI->crtFct; i++) {
		printf("\tFonction niveau %d: ", pI->fctLvls[i]);
		afficherFonction(pI->fctPtrs[i]);
	}
}
